/*
 * Copyright (c) 2022 Hong Jiahua
 * https://gitee.com/arrco/jh_dynamic_deque2
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef __JH_DYNAMIC_DEQUE_H__
#define __JH_DYNAMIC_DEQUE_H__

#include <stdlib.h>

#define jh_dynamic_deque_malloc    malloc
#define jh_dynamic_deque_realloc   realloc
#define jh_dynamic_deque_free      free
#define jh_dynamic_deque_qsort     qsort

#include <string.h>

// #define jh_dynamic_deque_memcpy    memcpy
// #define jh_dynamic_deque_memmove   memmove

/**
  * @brief  动态双端队列数据结构
  */
typedef struct {
    void* base;
    size_t num;
    size_t capacity;
    size_t size;
    size_t head;
    size_t tail;
} jh_dynamic_deque_t;

#define JH_DYNAMIC_DEQUE_INIT_CAPACITY 8

#define __JH_DYNAMIC_DEQUE_COUNT_ARGSCOUNT_ARGS(_0, _1, _2, _n, X...) _n
#define JH_DYNAMIC_DEQUE_COUNT_ARGS(X...) __JH_DYNAMIC_DEQUE_COUNT_ARGSCOUNT_ARGS(, ##X, 2, 1, 0)

#define __JH_DYNAMIC_DEQUE_CONCATL(a, b) a ## b
#define JH_DYNAMIC_DEQUE_CONCATENATEL(a, b) __JH_DYNAMIC_DEQUE_CONCATL(a, b)

#define jh_dynamic_deque_init_0()              jh_dynamic_deque_create(JH_DYNAMIC_DEQUE_INIT_CAPACITY, 1)
#define jh_dynamic_deque_init_1(_size)         jh_dynamic_deque_create(JH_DYNAMIC_DEQUE_INIT_CAPACITY, _size)
#define jh_dynamic_deque_init_2(_num, _size)   jh_dynamic_deque_create(_num, _size)
#define jh_dynamic_deque_init(...) JH_DYNAMIC_DEQUE_CONCATENATEL(jh_dynamic_deque_init_, JH_DYNAMIC_DEQUE_COUNT_ARGS(__VA_ARGS__)) (__VA_ARGS__)
/**
  * @brief  动态双端队列数据迭代
  */
#define JH_DYNAMIC_DEQUE_ITER(deque, item)    \
    for(size_t jh_i = (deque)->head != (deque)->tail ? memcpy(item, (deque)->base + (deque)->head * (deque)->size, (deque)->size) , (deque)->head: (deque)->head; \
        jh_i != (deque)->tail; jh_i = (jh_i + 1) % (deque)->capacity , jh_i = (jh_i != (deque)->tail) ? memcpy(item, (deque)->base + jh_i * (deque)->size, (deque)->size) , jh_i : jh_i)

/**
  * @brief  动态双端队列数据反向迭代
  */
#define JH_DYNAMIC_DEQUE_ITER_REVERSE(deque, item)    \
    for(size_t jh_i = (deque)->head != (deque)->tail ? jh_i = (deque)->tail ? (deque)->tail - 1 : (deque)->capacity - 1 , memcpy(item, (deque)->base + jh_i * (deque)->size, (deque)->size) , jh_i: (deque)->head, jh_j = jh_i; \
        jh_i != (deque)->head; jh_i = jh_j, jh_j = (jh_j == (deque)->head) ? (deque)->head : (jh_j = jh_j ? jh_j - 1 : (deque)->capacity - 1 , memcpy(item, (deque)->base + jh_j * (deque)->size, (deque)->size), jh_j))

/*判断动态双端队列是否为空*/
int jh_dynamic_deque_is_empty(jh_dynamic_deque_t* deque);
/*判断动态双端队列是否已满*/
int jh_dynamic_deque_is_full(jh_dynamic_deque_t* deque);
/*获取动态双端队列的数据数量*/
size_t jh_dynamic_deque_count(jh_dynamic_deque_t* deque);
/*获取动态双端队列的大小*/
size_t jh_dynamic_deque_size(jh_dynamic_deque_t* deque);
/*获取动态双端队列的容量*/
size_t jh_dynamic_deque_capacity(jh_dynamic_deque_t* deque);
/*数据添加到队首*/
int jh_dynamic_deque_push_head(jh_dynamic_deque_t* deque, void* item);
/*数据添加到队尾*/
int jh_dynamic_deque_push_tail(jh_dynamic_deque_t* deque, void* item);
/*强制数据添加到队首*/
int jh_dynamic_deque_force_push_head(jh_dynamic_deque_t* deque, void* item);
/*强制数据添加到队尾*/
int jh_dynamic_deque_force_push_tail(jh_dynamic_deque_t* deque, void* item);
/*队首数据出队*/
int jh_dynamic_deque_pop_head(jh_dynamic_deque_t* deque, void* item);
/*队尾数据出队*/
int jh_dynamic_deque_pop_tail(jh_dynamic_deque_t* deque, void* item);
/*查看队首的数据*/
int jh_dynamic_deque_peek_head(jh_dynamic_deque_t* deque, void* item);
/*查看队尾的数据*/
int jh_dynamic_deque_peek_tail(jh_dynamic_deque_t* deque, void* item);
/*调整动态双端队列大小*/
int jh_dynamic_deque_resize(jh_dynamic_deque_t* deque, size_t num);
/*压缩动态双端队列的容量到合适大小*/
int jh_dynamic_deque_shrink_to_fit(jh_dynamic_deque_t* deque);
/*清空动态双端队列*/
int jh_dynamic_deque_clear(jh_dynamic_deque_t* deque);
/*获取动态双端队列指定位置的指定数量数据*/
int jh_dynamic_deque_get_data(jh_dynamic_deque_t* deque, void* item, size_t start, size_t num);
/*动态双端队列数据排序*/
int jh_dynamic_deque_sort(jh_dynamic_deque_t* deque, int (*compare)(const void*, const void*));
/*创建动态双端队列*/
jh_dynamic_deque_t* jh_dynamic_deque_create(size_t num, size_t size);
/*销毁动态双端队列*/
void jh_dynamic_deque_destroy(jh_dynamic_deque_t* deque);

#endif